﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;

namespace TeaCompiler.CodeDom {

    /// <summary>
    /// 表示字面量表达式。
    /// </summary>
    public abstract class Literal : Expression {

    }

    /// <summary>
    /// 表示常量表达式。
    /// </summary>
    public abstract class Constant : Literal {

        public abstract string Name {
            get;
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        public override Location EndLocation {
            get {
                return StartLocation + Name.Length;
            }
            set {
                StartLocation = value - Name.Length;
            }
        }

        public override void Write(IndentedTextWriter writer) {
            writer.Write(Name);
        }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString() {
            return Name;
        }

    }

    /// <summary>
    /// 表示一个空表达式。
    /// </summary>
    public class EmptyExpression : Constant {

        public override string Name {
            get {
                return String.Empty;
            }
        }

    }

    /// <summary>
    /// 表示一个 null 常量。
    /// </summary>
    public class NullLiteral : Constant {

        public override string Name {
            get {
                return "null";
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitThisLiteral(this);
        //}

    }

    /// <summary>
    /// 标识符的常量。
    /// </summary>
    public class TrueLiteral : Constant {

        public override string Name {
            get {
                return "true";
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitTrueLiteral(this);
        //}

    }

    /// <summary>
    /// 标识符的常量。
    /// </summary>
    public class FalseLiteral : Constant {

        public override string Name {
            get {
                return "false";
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitFalseLiteral(this);
        //}

    }

    /// <summary>
    /// 标识符的常量。
    /// </summary>
    public class ThisLiteral : Constant {

        public override string Name {
            get {
                return "this";
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitThisLiteral(this);
        //}

    }

    /// <summary>
    /// 标识符的常量。
    /// </summary>
    public class BaseLiteral : Constant {

        public override string Name {
            get {
                return "base";
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitThisLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个字面常量。
    /// </summary>
    public class NumberLiteral : Constant {

        public TokenType Type {
            get;
            set;
        }

        /// <summary>
        /// 获取值。
        /// </summary>
        public string Value {
            get;
            set;
        }

        public override string Name {
            get {
                return Value;
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitNumberLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个字面常量。
    /// </summary>
    public class StringLiteral : Constant {

        public TokenType Type {
            get;
            set;
        }

        /// <summary>
        /// 获取值。
        /// </summary>
        public string Value {
            get;
            set;
        }

        public override string Name {
            get {
                return String.Concat(Type.GetName(), Value, Type.GetName());
            }
        }

        ////[System.Diagnostics.DebuggerStepThrough]
        ////public override void Accept(IAstVisitor visitor) {
        ////    visitor.VisitStringLiteral(this);
        ////}

        //public override void GenerateC(IndentedTextWriter writer) {
        //    writer.Write('"');
        //    writer.Write(Value.Replace("\"", "\\\"").Replace("\'", "\\\'").Replace("\n", "\\n").Replace("\r", "\\r"));
        //    writer.Write('"');
        //}
    }

    /// <summary>
    /// 表示一个正则表达式常量。
    /// </summary>
    public class RegExpLiteral : Constant {

        /// <summary>
        /// 获取模式。
        /// </summary>
        public string Pattern {
            get;
            set;
        }

        /// <summary>
        /// 获取标记。
        /// </summary>
        public string Flags {
            get;
            set;
        }

        public override string Name {
            get {
                return String.Concat('/', Pattern, '/', Flags);
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitRegExpLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个正则表达式常量。
    /// </summary>
    public class WideCharLiteral : Constant {

        /// <summary>
        /// 获取模式。
        /// </summary>
        public string Pattern {
            get;
            private set;
        }

        public override string Name {
            get {
                return String.Concat('%', Pattern, '%');
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitRegExpLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个正则表达式常量。
    /// </summary>
    public class XmlLiteral : Constant {

        /// <summary>
        /// 获取模式。
        /// </summary>
        public string Value {
            get;
            private set;
        }

        public override string Name {
            get {
                return Value;
            }
        }

    }

    /// <summary>
    /// 表示一个数组表达式。
    /// </summary>
    public class ArrayLiteral : Literal {

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location StartLocation {
            get {
                return Values.Count > 0 ? Values[0].StartLocation : Location.Empty;
            }
            set {
                if (Values.Count > 0) {
                    Values[0].EndLocation = value;
                }
            }
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get {
                return Values.Count > 0 ? Values[Values.Count - 1].EndLocation : Location.Empty;
            }
            set {
                if (Values.Count > 0) {
                    Values[Values.Count - 1].EndLocation = value;
                }
            }
        }

        /// <summary>
        /// 获取值。
        /// </summary>
        public List<Expression> Values {
            get;
            set;
        }

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            bool appendComma = false;
            foreach (Expression e in Values) {
                if (appendComma) {
                    writer.Write(',');
                    writer.Write(' ');
                } else {
                    appendComma = true;
                }

                e.Write(writer);
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitArrayLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个列表表达式。
    /// </summary>
    public class ListLiteral : ArrayLiteral {

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location StartLocation {
            get;
            set;
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get;
            set;
        }

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            writer.Write('[');
            base.Write(writer);
            writer.Write(']');
        }

    }

    /// <summary>
    /// 表示一个对象常量。
    /// </summary>
    public class DictionaryLiteral : Literal {

        /// <summary>
        /// 表示 DictionaryLiteral 的 键/值 属性对。
        /// </summary>
        public class Property : Node {

            /// <summary>
            /// 获取属性的键。
            /// </summary>
            public Identifier Key {
                get;
                set;
            }

            /// <summary>
            /// 获取属性的值。
            /// </summary>
            public Expression Value {
                get;
                set;
            }

            public override Location StartLocation {
                get {
                    return Key.EndLocation;
                }
                set {
                    Key.EndLocation = value;
                }
            }

            public override Location EndLocation {
                get {
                    return Value.EndLocation;
                }
                set {
                    Value.EndLocation = value;
                }
            }

            public override void Write(IndentedTextWriter writer) {
                Key.Write(writer);
                writer.Write(':');
                writer.Write(' ');
                Value.Write(writer);
            }

            //[System.Diagnostics.DebuggerStepThrough]
            //public override void Accept(IAstVisitor visitor) {
            //    visitor.VisitProperty(this);
            //}

            //public override void GenerateC(IndentedTextWriter writer) {

            //}
        }

        /// <summary>
        /// 获取值。
        /// </summary>
        public List<Property> Values {
            get;
            set;
        }

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            writer.Write('{');
            writer.Indent++;
            bool appendComma = false;
            foreach (Property p in Values) {
                if (appendComma) {
                    writer.Write(',');
                    writer.WriteLine();
                } else {
                    appendComma = true;
                }

                p.Write(writer);
            }

            writer.WriteLine();
            writer.Indent--;
            writer.Write('}');
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitObjectLiteral(this);
        //}

    }

    /// <summary>
    /// 表示一个函数表达式。
    /// </summary>
    public class FunctionLiteral : Literal {

        public enum FunctionStype {

            /// <summary>
            /// type fn(){}
            /// </summary>
            None,

            /// <summary>
            /// function fn(){}
            /// </summary>
            Function,

            /// <summary>
            /// e => {}
            /// </summary>
            SingleParamLambda,

            /// <summary>
            /// (e) => {}
            /// </summary>
            Lambda,
        }

        public class Param : Node {

            public bool ByRef {
                get;
                set;
            }

            //public bool Params {
            //    get;
            //    set;
            //}

            public Identifier Name {
                get;
                set;
            }

            public Expression Type {
                get;
                set;
            }

            public Expression DefaultValue {
                get;
                set;
            }

            public override void Write(IndentedTextWriter writer) {
                if (ByRef) {
                    writer.Write("ref ");
                }

                if (Type != null) {
                    Type.Write(writer);
                    writer.Write(' ');
                }

                if (Name != null) {
                    Name.Write(writer);
                } else {
                    writer.Write('?');
                }

                if (DefaultValue != null) {
                    writer.Write('=');
                    DefaultValue.Write(writer);
                }
            }

            //public override void GenerateC(IndentedTextWriter writer) {

            //}
        }

        public Modifier Modifier {
            get;
            set;
        }

        public Expression ReturnType {
            get;
            set;
        }

        public TokenType Type {
            get;
            set;
        }

        public FunctionStype Stype {
            get;
            set;
        }

        /// <summary>
        /// 获取名字。
        /// </summary>
        public Expression Name {
            get;
            set;
        }

        ///// <summary>
        ///// 获取作用域。
        ///// </summary>
        //public Object Scope {
        //    get;
        //    private set;
        //}

        public List<Param> Params {
            get;
            set;
        }

        /// <summary>
        /// 获取主体。
        /// </summary>
        public Statement Statement {
            get;
            set;
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get {
                return Statement.EndLocation;
            }
            set {
                Statement.EndLocation = value;
            }
        }

        //#region IScope 成员


        //public void AddSymbol(string name, TokenType declType) {
        //    _block.AddSymbol(name, declType);
        //}

        //public TokenType GetSymbol(string name) {
        //    return _block.GetSymbol(name);
        //}

        //public IScopeNode GetDefinedBlock(string name) {
        //    return _block.GetDefinedBlock(name);
        //}

        public override void Write(IndentedTextWriter writer) {

            writer.Write(Modifier.GetName());

            if (ReturnType != null) {
                ReturnType.Write(writer);
                writer.Write(' ');
            } else if (Stype == FunctionStype.Function) {
                writer.Write("function ");
            }
            if (Stype == FunctionStype.SingleParamLambda) {
                Params[0].Name.Write(writer);
            } else {

                if (Name != null) {
                    Name.Write(writer);
                }

                writer.Write('(');

                bool appendComma = false;
                foreach (Param p in Params) {
                    if (appendComma)
                        writer.Write(", ");
                    else
                        appendComma = true;

                    p.Write(writer);
                }

                writer.Write(')');

            }

            if (Stype != FunctionStype.None) {
                writer.Write(" => ");
            }

            Statement.Write(writer);
        }

        //#endregion


        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitFunctionExpression(this);
        //}

        //NodeList<FunctionDeclaration> _fns;

        //public NodeList<FunctionDeclaration> Functions {
        //    get {

        //        if (_fns == null)
        //            _fns = new NodeList<FunctionDeclaration>();
        //        return _fns;
        //    }
        //}

        //public void AddFunction(FunctionDeclaration fn) {
        //    AddSymbol(fn.Name, TokenType.Var);

        //    Functions.Add(fn);
        //}

    }

    //public class ClassExpression : Expression {

    //    public ClassExpression(Location location)
    //        : base(location) {

    //    }

    //    public override Location EndLocation {
    //        get {
    //            return Location.Empty;
    //        }
    //    }

    //    public override void Accept(IAstVisitor visitor) {

    //    }
    //}

    //public class FunctionParam : Node {

    //    public override Location EndLocation {
    //        get {
    //            throw new NotImplementedException();
    //        }
    //    }

    //    //public override void Accept(IAstVisitor visitor) {
    //    //    throw new NotImplementedException();
    //    //}

    //    //public override void Write(IndentedTextWriter writer) {
    //    //    throw new NotImplementedException();
    //    //}

    //    //public override void GenerateC(IndentedTextWriter writer) {
    //    //    throw new NotImplementedException();
    //    //}
    //}

}
